#include "DeviceZigbee.h"
#include "tool.h"
#include <iostream>
#define smoke_alarm_pid "4753353239412D42"

using namespace std;

long z3_len_get(long val_len);

DeviceZigbee::DeviceZigbee (string data1,string data2){
    this->gs529AStatus = NULL;
    this->socketStatus = NULL;
    this->pirStatus = NULL;
    this->wleakStatus = NULL;
    this->htDetectorStatus = NULL;
    this->addProductEvent = NULL;
    this->handlerDevStatus(data1,data2,0);
}

DeviceZigbee::DeviceZigbee (string data1,string data2,int sync){
    this->gs529AStatus = NULL;
    this->socketStatus = NULL;
    this->pirStatus = NULL;
    this->wleakStatus = NULL;
    this->htDetectorStatus = NULL;
    this->addProductEvent = NULL;
    
    this->handleSyncData(data1,data2);
}


//实时上报数据解析
void DeviceZigbee::handlerDevStatus(string data1,string data2,int sync){

    if(data1.empty()||data2.empty()){
        if(sync==0)
        this->result_err = ERR_NULL_STRING;
        return;
    }

    if(data1.size()!=10 || data2.size()<8){
        if(sync==0)
        this->result_err  = ERR_STRING_LEN;
        return;
    }

    string str2_length = data1.substr(8,2);

    int de = StrToDemicalData(str2_length);

    if(de ==0 || data2.size()<de*2){
        if(sync==0)
        this->result_err = ERR_STRING_LEN;
        return;
    }

    this->result_err = ERR_OK;

    this->address = StrToDemicalData(data1.substr(0,4));

    string clusterIdM = data1.substr(4,4);
    if(sync==0) this->clusterId = clusterIdM;
    string head = data2.substr(0,2);
    string type = data2.substr(4,8);
    if(head=="18"&&type=="0A050042"&&clusterIdM=="0000"){
        string length_str = data2.substr(12,2);
        int leng = StrToDemicalData(length_str);
        if((14+leng*2)>data2.size()){
            if(sync==0)
            this->result_err = ERR_STRING_LEN;
        }else{
            string aaa = data2.substr(14,leng*2);
            int ad = sizeof(long);
            int ad2 = sizeof(char)*(leng*2+1);
            if(this->addProductEvent == NULL)
            this->addProductEvent =   (AddProductEvent *)malloc(ad+ad2);
            this->addProductEvent->address =  this->address;
            this->addProductEvent->productKey = (char *)malloc(sizeof(char)*(leng*2+1));

            memcpy(this->addProductEvent->productKey,aaa.c_str(),leng*2);
            *(this->addProductEvent->productKey+leng*2) = '\0';
        }
    }else{
        if(clusterIdM=="0019"){
            string aaa = smoke_alarm_pid;
            int ad = sizeof(long);
            int ad2 = sizeof(char)*(aaa.size()+1);
            if(this->addProductEvent == NULL)
            this->addProductEvent =   (AddProductEvent *)malloc(ad+ad2);
            this->addProductEvent->address =  this->address;
            this->addProductEvent->productKey = (char *)malloc(sizeof(char)*(aaa.size()+1));

            memcpy(this->addProductEvent->productKey,aaa.c_str(),aaa.size());
            *(this->addProductEvent->productKey+aaa.size()) = '\0';
        }
        else if(clusterIdM=="0006"){
            if(data2.size()<14){
                if(sync==0)
                this->result_err = ERR_STRING_LEN;

            }else{
                string socketType = data2.substr(10,2);
                string socket = data2.substr(12,2);
                if(this->socketStatus == NULL)
                this->socketStatus = (SocketStatus *)malloc(sizeof(SocketStatus));
                if(socketType=="10"){
                    if(socket=="01"){
                        this->socketStatus->socketStatus = 1;
                    }else{
                        this->socketStatus->socketStatus = 0;
                    }
                }else if(socketType=="20"){
                    this->socketStatus->socketStatus = 2;
                }else{
                    if(sync==0)
                    this->result_err = ERR_DATA_RANGE;
                }

            }
        }else if(clusterIdM=="0500"){
            string typeheader = data2.substr(0,2);
            if("09" == typeheader){
                if(data2.size()<12){
                    if(sync==0)
                    this->result_err = ERR_STRING_LEN;
                }else{
                    if(this->gs529AStatus == NULL)
                    this->gs529AStatus = (GS529ABStatus *)malloc(sizeof(GS529ABStatus));
                    string hight_str = data2.substr(8,2);

                    string low_str = data2.substr(10,2);

                    long low_data = StrToDemicalData(low_str);
                    long high_data = StrToDemicalData(hight_str);

                    this->gs529AStatus->alarm_status = ((0x01 & low_data) ==0?0:1);
                    this->gs529AStatus->tamper = ((0x04 & low_data) ==0?0:1);

                    this->gs529AStatus->low_battery = ((0x08 & low_data) ==0?0:1);
                    this->gs529AStatus->fault = ((0x40 & low_data) ==0?0:1);
                    this->gs529AStatus->test_alarm_status = ((0x01 & high_data) ==0?0:1);
                    this->gs529AStatus->remote_alarm_status = ((0x04 & high_data) ==0?0:1);
                    this->gs529AStatus->hush_status = ((0x08 & high_data) ==0?0:1);
                    this->gs529AStatus->end_life = ((0x10 & high_data) ==0?0:1);
                }

            }else if("19" == typeheader){
                if(data2.size()<10){
                    if(sync==0)
                    this->result_err = ERR_STRING_LEN;
                }else{
                    if(this->wleakStatus == NULL)
                    this->wleakStatus = (WLeakStatus *)malloc(sizeof(WLeakStatus));
                    string status = data2.substr(6,4);
                    if("0000"==status)
                        this->wleakStatus->alarm_status = 0;
                    else
                        this->wleakStatus->alarm_status = 1;
                }

            }else{
                if(sync==0)
                this->result_err = ERR_DATA_RANGE;
            }

        }else if(clusterIdM=="0406"){
            if(this->pirStatus == NULL)
            this->pirStatus = (PirStatus *)malloc(sizeof(PirStatus));
            this->pirStatus->has_people=1;
        }else if(clusterIdM=="0402"){
            if(data2.size()<16){
                if(sync==0)
                this->result_err = ERR_STRING_LEN;
            }else{
                if(this->htDetectorStatus == NULL){
                    this->htDetectorStatus = (HTDetectorStatus *)malloc(sizeof(HTDetectorStatus));
                    this->htDetectorStatus->hump = NULL;
                }
                string high_str = data2.substr(14,2);
                long high_data = StrToDemicalData(high_str);
                long high_data_2 = (0x7F & high_data);
                bool flag_fu = ((0x80 & high_data) !=0);
                this->htDetectorStatus->isMinus = flag_fu;
                char *de = (char *)malloc(sizeof(char)*3);
                longToStr(high_data_2,de);
                *(de+2) = '\0';
                string low_str = data2.substr(12,2);
                int *temp = (int *)malloc(sizeof(int));
                int aa = StrToDemicalData(((string)de)+low_str);
                *temp = aa/100;
                this->htDetectorStatus->temp = temp;
                free(de);
            }

        }else if(clusterIdM=="0405"){
            if(data2.size()<16){
                if(sync==0)
                this->result_err = ERR_STRING_LEN;
            }else{
                if(this->htDetectorStatus == NULL){
                    this->htDetectorStatus = (HTDetectorStatus *)malloc(sizeof(HTDetectorStatus));
                    this->htDetectorStatus->temp = NULL;
                }
                string high_str = data2.substr(14,2);
                string low_str = data2.substr(12,2);
                int *hum = (int *)malloc(sizeof(int));
                *hum  = StrToDemicalData(high_str+low_str)/100;
                this->htDetectorStatus->hump = hum;
            }

        }
        else{
            if(sync==0)
            this->result_err = ERR_DATA_RANGE;
        }
    }

}


//设备分包同步数据上报数据解析
void DeviceZigbee::handleSyncData(string data1,string data2){
    if(data2.empty()){
        this->result_err = ERR_NULL_STRING;
        return;
    }

    if(data2.size()<8||data1.size()!=8){
        this->result_err  = ERR_STRING_LEN;
        return;
    }

    string address_str = data1.substr(0,4);
    string attr_count_str = data1.substr(4,2);
    string byte_count_str = data1.substr(6,2);
    int attr_count = StrToDemicalData(attr_count_str);
    int byte_count = StrToDemicalData(byte_count_str);
     if((data2.size()+2)!=byte_count*2){
        this->result_err  = ERR_STRING_LEN;
        return;
     }
     
     long c_alarm = 0;
     long count = 0;
     do
     {

        if(data2.size()<12){
            this->result_err = ERR_NULL_STRING;
            return;
        }

        string clusterId = data2.substr(0,4);
        string identifer_low = data2.substr(4,2);
        string identifer_high = data2.substr(6,2);
        string identifer = identifer_high + identifer_low;
        string identifer_type = data2.substr(8,2);
        string dentifer_value;
       long len = z3_len_get(StrToDemicalData(identifer_type));
       long len_item = 0;
        if(len==255){
            long len_str = StrToDemicalData(data2.substr(10,2));
            len_item = 6+len_str;
            dentifer_value = data2.substr(10,2) + data2.substr(12,len_str*2);
        }else{
           len_item = 5+len;
           dentifer_value = data2.substr(10,len*2);
        }
        if(len_item*2>data2.size()){
            this->result_err = ERR_NULL_STRING;
            return;
        }
    
        string content = "";
        if(clusterId=="0500" && identifer_high=="30"){
            c_alarm = 1;
            content = "090000" + identifer + identifer_type + dentifer_value;
        }else if(clusterId=="0500" && identifer_high=="01"){
            c_alarm = 2;
            content = "190000" + identifer + identifer_type + dentifer_value;
        }else if(clusterId=="0500" && identifer_high=="00"){
            if(c_alarm==1){
                content = "090000" + identifer + identifer_type + dentifer_value;
            }else if(c_alarm==2){
                content = "190000" + identifer + identifer_type + dentifer_value;
            }else{
                long lena = data2.size();
                data2 = data2.substr(len_item*2,lena);
                count++;
                continue;
            }

        }else{
            content = "18000A" + identifer + identifer_type + dentifer_value;
        }

        char *de = (char *)malloc(sizeof(char)*3);
        longToStr(content.size()/2,de);
        *(de+2) = '\0';

        string data1_aa = address_str + clusterId + ((string)de);
        this->handlerDevStatus(data1_aa,content,1);

        free(de);

        long lena = data2.size();
        data2 = data2.substr(len_item*2,lena);
        count++;
     } while (count<attr_count);
     
     if(this->socketStatus==NULL&& this->gs529AStatus==NULL&& this->wleakStatus==NULL&& this->pirStatus==NULL&& this->htDetectorStatus==NULL&& this->addProductEvent==NULL){
        this->result_err = ERR_DATA_INVALID;
     }
     
   
     string contentest = "";
     
     cout << contentest << endl;
}

long z3_len_get(long val_len)//获取属性值数据类型长度
{
    long k;
    if(val_len==0)
        return 0;
    if((val_len&0xf0)>0x30){
        return 0xff;// 2022_8_6 表示下一个字符才是真实长度
    }
    k   =   val_len&0x0f;
    if(k>7){
        return(k-7);
    }else{
        return(k+1);
    }
} 